using System;
using System.Xml;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using GuavaData;

namespace GuavaLib
{
    public partial class ClassifierBuilder : Form
    {
        public List<ClassifierWrapper> lcw;
        List<Column> listOfQueryColumns;
        
        public ClassifierBuilder(Scheme queryIn)
        {
            InitializeComponent();
            listOfQueryColumns = new List<Column>();

            foreach (Column c in queryIn.columns)
            {
                this.QueryColumns.Items.Add(c);
                this.listOfQueryColumns.Add(c);
            }
            this.QueryColumns.DisplayMember = "Name";
            this.SchemaColumns.DisplayMember = "Name";

            lcw = new List<ClassifierWrapper>();

            this.SchemaColumns.DrawItem += new DrawItemEventHandler(SchemaColumns_DrawItem);
            this.SchemaColumns.DoubleClick += new EventHandler(SchemaColumns_DoubleClick);
        }

        void SchemaColumns_DoubleClick(object sender, EventArgs e)
        {
            if (SchemaColumns.SelectedIndex < 0) return;
            Column cTemp = SchemaColumns.SelectedItem as Column;

            ClassifierWrapper cwTemp = new ClassifierWrapper(new List<Column>(), cTemp, "", "");
            foreach (ClassifierWrapper cwIndex in lcw)
            {
                if (cwIndex.output.Name == cTemp.Name)
                {
                    cwTemp = cwIndex;
                    break;
                }
            }

            SingleClassifierBuilder scb = new SingleClassifierBuilder(cTemp, this.listOfQueryColumns, cwTemp);
            if (scb.ShowDialog() == DialogResult.OK)
            {
                lcw.Remove(cwTemp);
                lcw.Add(scb.Classifier);
            }
        }

        void SchemaColumns_DrawItem(object sender, DrawItemEventArgs e)
        {
            if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
            {
                e.Graphics.FillRectangle(Brushes.CornflowerBlue, e.Bounds);
            }
            else
            {
                // Find out if there is no classifier defined for an item
                Column toTest = SchemaColumns.Items[e.Index] as Column;
                bool bFound = false;
                foreach (ClassifierWrapper cw in this.lcw)
                {
                    if (cw.output.Name == toTest.Name) bFound = true;
                }
                
                // If yes, draw the rectangle filled in beige.
                if (bFound)
                    e.Graphics.FillRectangle(Brushes.Beige, e.Bounds);
                else
                    e.Graphics.FillRectangle(Brushes.Red, e.Bounds);
            }

            // Draw a rectangle in blue around each item.
            e.Graphics.DrawRectangle(Pens.Blue, e.Bounds);

            // Draw the text in the item.
            e.Graphics.DrawString(SchemaColumns.Items[e.Index].ToString(),
                this.Font, Brushes.Black, e.Bounds.X, e.Bounds.Y);

            // Draw the focus rectangle around the selected item.
            e.DrawFocusRectangle();
        }

        private void QueryColumns_SelectedIndexChanged(object sender, EventArgs e)
        {
            Column c = QueryColumns.SelectedItem as Column;
            String str = c.Name;
            GuavaData.Domain.Domain dom = c.dom;

            // Fix the domain listed
            QueryColumnDomain.Items.Clear();
            if (dom.ListOutput() == null)
                QueryColumnDomain.Items.Add(dom);
            else
                foreach (object obj in dom.ListOutput())
                    QueryColumnDomain.Items.Add(obj);
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;
            this.Close();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }

        private void SchemaColumns_SelectedIndexChanged(object sender, EventArgs e)
        {
            Column c = SchemaColumns.SelectedItem as Column;
            if (c == null) return;
            GuavaData.Domain.Domain dom = c.dom;

            // Fix the domain listed
            SchemaColumnDomain.Items.Clear();
            if (dom.ListOutput() == null)
                SchemaColumnDomain.Items.Add(dom);
            else
                foreach (object obj in dom.ListOutput())
                    SchemaColumnDomain.Items.Add(obj);
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            if (SchemaColumns.SelectedIndex < 0) return;
            if (MessageBox.Show("Do you really want to delete this column from your schema?") == DialogResult.OK)
            {
                Column cTemp = SchemaColumns.Items[SchemaColumns.SelectedIndex] as Column;
                SchemaColumns.Items.Remove(cTemp);

                ClassifierWrapper cwTemp = null;
                foreach (ClassifierWrapper cw in lcw) if (cw.output.Name == cTemp.Name)
                    {
                        cwTemp = cw;
                        break;
                    }

                if (cwTemp != null) lcw.Remove(cwTemp);
            }
            SchemaColumnDomain.Items.Clear();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            InitialColumnDefinitionForm icdf = new InitialColumnDefinitionForm();
            if (icdf.ShowDialog() == DialogResult.OK)
                SchemaColumns.Items.Add(new Column(icdf.ColumnName, icdf.ColumnDomain));
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (this.txtSchemaName.Text == null || this.txtSchemaName.Text.Length == 0)
            {
                MessageBox.Show("You must enter a schema name before saving.");
                return;
            }

            if (this.txtSchemaNotes.Text == null || this.txtSchemaNotes.Text.Length == 0)
            {
                MessageBox.Show("You must enter schema comments before saving.");
                return;
            }

            if (this.SchemaColumns.Items.Count == 0)
            {
                MessageBox.Show("You must have at least one column before saving.");
                return;
            }
            
            if (saveSchemaDialog.ShowDialog() == DialogResult.OK)
            {
                // Build list of columns
                List<Column> lc = new List<Column>();
                foreach (Column c in SchemaColumns.Items) lc.Add(c);

                XmlDocument xd = (new ClassSchema(lc, this.txtSchemaName.Text, this.txtSchemaNotes.Text)).ToXml();
                xd.Save(saveSchemaDialog.FileName);
            }
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            if (loadSchemaDialog.ShowDialog() == DialogResult.OK)
            {
                XmlReader xr = XmlReader.Create(loadSchemaDialog.FileName);
                xr.Read();
                XmlDocument xd = new XmlDocument();
                xd.Load(xr);
                
                ClassSchema cs = ClassSchema.ParseXml(xd);
                this.txtSchemaName.Text = cs.name;
                this.txtSchemaNotes.Text = cs.comments;
                this.SchemaColumns.Items.Clear();
                foreach (Column c in cs.columns) this.SchemaColumns.Items.Add(c);
            }
        }

        private void btnReplicate_Click(object sender, EventArgs e)
        {
            SchemaColumns.Items.Clear();
            this.lcw.Clear();
            foreach (Column c in QueryColumns.Items)
            {
                SchemaColumns.Items.Add(c);
                lcw.Add(new ClassifierWrapper(new Column[] { c }, c, String.Concat("==> [[", c.Name, "]]"), ""));
            }
        }
    }
}